home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Medal Software 2
/
Gold Medal Software Volume 2 (Gold Medal) (1994).iso
/
prog
/
asm_n_z.arj
/
RECEIVE.ASM
< prev
next >
Wrap
Assembly Source File
|
1986-07-14
|
17KB
|
393 lines
Page 55,132
Title SEND - Send a file using XMODEM protocol
SPECIAL Equ 0 ;If true, include data size in block
If SPECIAL
BLOCK Struc
B_SOH Db 001H ;Start of header
B_BLK1 Db 000H ;Block number
B_BLK2 Db 0FFH ;(Block number)'
B_CNT Db ? ;Count of bytes used in the data area
B_DATA Db 128 Dup (?) ;The data area
B_CHKSUM Db ? ;Checksum of the data
BLOCK Ends
Else
BLOCK Struc
B_SOH Db 001H ;Start of header
B_BLK1 Db 000H ;Block number
B_BLK2 Db 0FFH ;(Block number)'
B_DATA Db 128 Dup (?) ;The data area
B_CHKSUM Db ? ;Checksum of the data
BLOCK Ends
Endif
ERROR Macro N
Mov AH,09H ;Display the error message
Lea DX,ERRMSG&N ;
Int 021H ;
Mov AX,04C10H+N ;And leave
Int 021H ;
Endm
CODE Segment Public 'CODE'
CODE Ends
DATA Segment Public 'DATA'
BAUD_TABLE Label Word
Dw 9600 ;
Dw 4800 ;
Dw 2400 ;
Dw 1200 ;
Dw 600 ;
Dw 300 ;
Dw 150 ;
Dw 110 ;
FILENAME Db 64 Dup (0) ;Name of file to send
BUFFER BLOCK <> ;The block buffer
ERRMSG0 Db '?No output file specified',13,10,'$'
ERRMSG1 Db '?Unable to create output file',13,10,'$'
ERRMSG2 Db '?Invalid baud rate specified',13,10,'$'
ERRMSG3 Db '?Transmitter time-out occurred',13,10,'$'
ERRMSG4 Db '?Error while writing the output file',13,10,'$'
ERRMSG5 Db '^C',13,10,'%Reception aborted via control-C',13,10,'$'
TXTMSG1 Db 'Waiting for transmitter...',13,10,'$'
TXTMSG2 Db 'Block number '
TXTNUM2 Db '0 ',13,'$'
TXTMSG3 Db 10,'Reception complete',13,10,'$'
TXTMSG4 Db 'No retries needed',13,10,'$'
TXTMSG5 Db 'Retry count was '
TXTNUM5 Db '0 ',13,10,'$'
MODE Db 11101011B ;9600 baud, odd parity, 1 stop bit,
;8 bit character
BLOCK_COUNT Dw 0 ;Total block count
RETRY_COUNT Dw 0 ;Retry count
BLK_NUM Db 001H ;8 bit block number expected.
DATA Ends
STACK Segment Stack 'STACK'
Dw 128 Dup (?) ;Program stack
STACK Ends
CODE Segment Public 'CODE'
Assume CS:CODE,DS:Nothing,ES:Nothing,SS:STACK
MAIN Proc Near
Sti ;Enable interrupts
Mov AX,DATA ;Set up ES
Mov ES,AX ;
Assume ES:DATA
Cld ;Make sure the direction flag is clear
Mov SI,080H ;Use SI to get the file name
Lodsb ;Get the length
Or AL,AL ;Is there anything??
Jnz MAIN01 ;Yes. Proceed
MAIN00: Mov AX,ES ;Set up DS
Mov DS,AX ;
Assume DS:DATA
ERROR 0 ;Nope. Die!
Assume DS:Nothing
MAIN01: Cbw ;Make it a word count
Mov CX,AX ;Copy to CX
MAIN05: Jcxz MAIN00 ;If nothing left, error!
Dec CX ;Decrement the character count
Lodsb ;And get the character
Cmp AL,020H ;Space or less??
Ja MAIN10 ;Nope. Start the file name
Jmp Short MAIN05 ;Try again...
MAIN10: Lea DI,FILENAME ;Point DI to the file name buffer
MAIN11: Stosb ;Store the character
Jcxz MAIN20 ;Got the file name. Open the file
Dec CX ;Decrement the character count
Lodsb ;Get the next character
Cmp AL,020H ;Is it a displayable character
Ja MAIN11 ;Yes. Put it in the file name
MAIN13: Jcxz MAIN20 ;No more characters?
Dec CX ;Decrement the count
Lodsb ;Get another character
Cmp AL,020H ;Space or less??
Ja MAIN15 ;Yes. See if it's a number
Jmp Short MAIN13 ;Keep looking
MAIN15: Xor DX,DX ;Clear DX
MAIN16: Cmp AL,'0' ;Is this a digit??
Jae MAIN18 ;Yes.
MAIN17: ERROR 2 ;Not a valid baud rate
MAIN18: Cmp AL,'9' ;Still a digit??
Ja MAIN17 ;Nope.
Sub AL,'0' ;Convert to binary
Cbw ;Convert to a word
Shl DX,1 ;Double the previous number
Mov BX,DX ;Save in BX for a bit
Shl DX,1 ;
Shl DX,1 ;
Add DX,BX ;Now DX = (Old DX)*10
Add DX,AX ;Add in the last digit
Jcxz MAIN19 ;All done.
Dec CX ;Decrement the character count
Lodsb ;And get a character
Cmp AL,020H ;Space or less?
Ja MAIN16 ;
MAIN19: Mov AX,DX ;Put the baud rate in AX
Lea DI,BAUD_TABLE ;Point to the baud rate table
Mov CX,8 ;Eight entries in the table
Repne Scasw ;Look for this baud rate
Jne MAIN17 ;No good! Die!
Mov AL,CL ;Get the index
Mov CL,5 ;And position it
Shl AL,CL ;
Or AL,00001011B ;Odd parity, 1 stop bit, 8 bit character
Mov MODE,AL ;And save it
MAIN20: Mov AX,ES ;Set up DS
Mov DS,AX ;
Assume DS:DATA
Mov AH,03CH ;Create the file specified
Xor CX,CX ;With no attributes
Lea DX,FILENAME ;
Int 021H ;
Jnc MAIN25 ;Proceed!
ERROR 1 ;Couldn't create the file
MAIN25: Mov BX,AX ;Put the handle in BX
Xor AH,AH ;Initialize the RS232 channel
Mov AL,MODE ;
Xor DX,DX ;On channel zero
Int 014H ;
Mov AH,09H ;Display the "Waiting..." message
Lea DX,TXTMSG1 ;
Int 021H ;
Mov CX,64 ;This shall be our original timeout
MAIN30: Mov AH,06H ;See if a character is waiting
Mov DL,0FFH ;
Int 021H ;
Jz MAIN32 ;Nope.
Cmp AL,3 ;Is it a control-C??
Jne MAIN32 ;
Mov AH,03EH ;Close the input file
Int 021H ;
ERROR 5 ;And die
MAIN32: Mov AX,0115H ;Send a NAK to the transmitter
Xor DX,DX ;(channel 0)
Int 014H ;
Push CX ;Save CX on the stack
Call GET_BLOCK ;Get a block of data
Pop CX ;Restore CX
Jnc MAIN35 ;Got one. Go check it.
MAIN31: Loop MAIN30 ;Repeat until CX = 0
Mov AH,03EH ;Close the input file
Int 021H ;
ERROR 3 ;And die!
MAIN35: Cmp BUFFER.B_SOH,04H ;Is this the end of the file??
Je MAIN80 ;Yes. Close the file and leave
Lea DI,TXTNUM2 ;Fill in the block number
Mov AX,BLOCK_COUNT ;
Call FILL_NUM ;
Mov AH,09H ;Display the block number
Lea DX,TXTMSG2 ;
Int 021H ;
Mov AH,040H ;Write the file...
If SPECIAL
Mov CL,BUFFER.B_CNT ;This many bytes only!
Xor CH,CH ;
Else
Mov CX,128 ;Up to 128 bytes
Endif
Lea DX,BUFFER.B_DATA ;From our buffer
Int 021H ;
Jnc MAIN40 ;Got it; now ship it
Mov AH,03EH ;Close the input file
Int 021H ;
ERROR 4 ;And die (for some unknown reason)
MAIN40: Mov AX,0105H ;Send an ACK
Xor DX,DX ;
Int 014H ;
MAIN42: Call GET_BLOCK ;Get another block
Jnc MAIN35 ;Check for EOF.
Mov AX,0115H ;Send another NAK (just in case)
Xor DX,DX ;
Int 014H ;
Jmp Short MAIN42 ;And try again
;
; End of file...
;
MAIN80: Mov AX,0105H ;Send a final ACK
Xor DX,DX ;
Int 014H ;
Mov AH,09H ;Display the EOT message
Lea DX,TXTMSG3 ;
Int 021H ;
Mov AH,03EH ;Close the input file
Int 021H ;
Cmp RETRY_COUNT,0 ;Did we have to do any retries??
Mov AH,09H ;No retries needed
Lea DX,TXTMSG4 ;
Int 021H ;
Jmp Short MAIN99 ;Leave
MAIN95: Lea DI,TXTNUM5 ;Point to the buffer
Mov AX,RETRY_COUNT ;Get the count
Call FILL_NUM ;
Mov AH,09H ;And display the message
Lea DX,TXTMSG5 ;
Int 021H ;
MAIN99: Mov AX,04C00H ;And leave
Int 021H ;
MAIN Endp
;
;
;
FILL_NUM Proc Near
Xor CX,CX ;Clear the character count
Mov SI,10 ;Use SI to divide with
FILL10: Xor DX,DX ;
Div SI ;Divide DX:AX by SI (10)
Add DL,'0' ;Convert DL to ASCII
Push DX ;Save it on the stack
Inc CX ;Increment the character count
Or AX,AX ;Any more to do??
Jnz FILL10 ;Yes. Keep going
Cld ;(just to be sure)
FILL20: Pop AX ;Get a character from the stack
Stosb ;And store it
Loop FILL20 ;Repeat CX times
Ret ;And return
FILL_NUM Endp
;
; Get a block from the transmitter
;
GET_BLOCK Proc Near
Cld ;(just to be sure)
Lea DI,BUFFER ;Point to the buffer
Mov CX,20 ;Time out for the first byte
GETB10: Mov AH,06H ;See if a character is waiting
Mov DL,0FFH ;
Int 021H ;
Jz GETB12 ;Nope.
Cmp AL,3 ;Is it a control-C??
Jne GETB12 ;
Mov AH,03EH ;Close the input file
Int 021H ;
ERROR 5 ;And die
GETB12: Mov AH,02H ;Get a character
Xor DX,DX ;
Int 014H ;
Test AH,08EH ;Any errors??
Jnz GETB14 ;Yup. Ignore it!
Cmp AL,01H ;SOH??
Je GETB20 ;Yes. Start the block
Cmp AL,04H ;End-of-text??
Je GETB15 ;Yes. Return it.
Jmp Short GETB12 ;Wait for another character
GETB14: Loop GETB10 ;Repeat until CX = 0
Stc ;Set the carry
Ret ;And return
GETB15: Stosb ;Store the EOT
Clc ;Clear carry...
Ret ;...and return
GETB20: Mov CX,(Size BLOCK-1) ;Repeat for the entire block
Stosb ;Store the SOH
GETB22: Mov SI,4 ;Use SI for a timeout count
GETB24: Mov AH,02H ;Wait for another character
Xor DX,DX ;
Int 014H ;
Test AH,080H ;Time-out??
Jz GETB26 ;Nope.
Dec SI ;Decrement the time-out count
Jnz GETB24 ;And try again
Jmp SEND_RETRY ;Send a retry
GETB26: Stosb ;Store the character
Loop GETB22 ;And try again
Mov AL,BLK_NUM ;Get the expected block number
Cmp AL,BUFFER.B_BLK1 ;Is this it??
Jne SEND_RETRY ;Nope.
Xor AL,0FFH ;Complement AL
Cmp AL,BUFFER.B_BLK2 ;Double check
Jne SEND_RETRY ;Nope.
Lea SI,BUFFER.B_DATA ;Compute the checksum
Xor AH,AH ;Clear AH
Xor DX,DX ;Keep the checksum in DX
Mov CX,128 ;Repeat for 128 bytes
GETB30: Lodsb ;Get a byte
Add DX,AX ;Add it to DX
Loop GETB30 ;And repeat
Mov AX,DX ;Put the sum in AX
Mov DL,255 ;Now divide by 255
Div DL ;
Cmp BUFFER.B_CHKSUM,AH ;See if the check sum is O.K.
Jne SEND_RETRY ;Nope. Send a retry
Inc BLK_NUM ;Increment the expected block number
Inc BLOCK_COUNT ;And the block count
Clc ;
Ret ;Otherwise return with carry clear
SEND_RETRY:
Mov AX,0115H ;Send a NAK
Xor DX,DX ;
Int 014H ;
Inc RETRY_COUNT ;Increment the retry count
Jmp GET_BLOCK ;And try all over again
GET_BLOCK Endp
CODE Ends
End MAIN